自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)

您所在的位置:网站首页 QT 自定义listwidget标题展开 自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)

自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)

2024-07-17 16:15:43| 来源: 网络整理| 查看: 265

本文转载自https://blog.csdn.net/weixin_43742643/article/details/100187743

前半部分copy了博主的博文,后面是自己的实践和疑惑。

效果图:

 

这里需要说明一下:QListWidget是鼠标press时item就会被选中,自定义的TestListWidget类重写了mousePressEvent和mouseReleaseEvent使得item在鼠标release时才会被选中。至于为什么这样做,是因为Chrome浏览器的书签栏以及网易云音乐的选项列表都是在鼠标release时才会触发选中…

本文中实现方法:

item被hover时改变图标样式:继承QListWidgetItem + 继承QListWidget item在鼠标release时选中:继承QListWidget

另一种实现方法:自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法二)

(1)TestListWidgetItem类继承自QListWidgetItem

TestListWidgetItem.h文件:

 

class TestListWidgetItem : public QListWidgetItem { //Q_OBJECT //由于QListWidgetItem没有QObject属性,所以Q_OBJECT需要注释掉 public: explicit TestListWidgetItem(QListWidget *view = nullptr); void setUpIcon(const QIcon &icon, const QIcon &icon_hover); QIcon Img; QIcon Img_hover; };

 

TestListWidgetItem.c文件: TestListWidgetItem::TestListWidgetItem(QListWidget *view) : QListWidgetItem(view) { } void TestListWidgetItem::setUpIcon(const QIcon &icon, const QIcon &icon_hover) { Img = icon; Img_hover = icon_hover; setIcon(Img); }

2)TestListWidget类继承自QListWidget

TestListWidget.h文件: class TestListWidget : public QListWidget { Q_OBJECT public: explicit TestListWidget(QWidget *parent = nullptr); protected: void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void leaveEvent(QEvent *event) override; private: QPoint startPos; TestListWidgetItem *theHighlightItem = nullptr; TestListWidgetItem *oldHighlightItem = nullptr; TestListWidgetItem *theSelectedItem = nullptr; TestListWidgetItem *oldSelectedItem = nullptr; private slots: void updateSelectedIcon(); }; TestListWidget.c文件: TestListWidget::TestListWidget(QWidget *parent) : QListWidget(parent) { //mouseMoveEvent(QMouseEvent *event)需要该属性 setMouseTracking(true); //当前被选中项发生变化时,触发item图标的更新 connect(this, &TestListWidget::itemSelectionChanged, this, &TestListWidget::updateSelectedIcon); } //处理鼠标hover时,item的图标需要变成hover状态 void TestListWidget::mouseMoveEvent(QMouseEvent *event) { oldHighlightItem = theHighlightItem; theHighlightItem = static_cast(itemAt(event->pos())); //旧的hover的item图标回复原状(条件是该item没有被选中) //新的hover的iten图标变成hover状态(条件是该item没有被选中) if(oldHighlightItem != theHighlightItem){ if(oldHighlightItem && !oldHighlightItem->isSelected()) oldHighlightItem->setIcon(oldHighlightItem->Img); if(theHighlightItem && !theHighlightItem->isSelected()) theHighlightItem->setIcon(theHighlightItem->Img_hover); } } //鼠标按下时,startPos记录单击位置 void TestListWidget::mousePressEvent(QMouseEvent *event) { if(event->buttons() & Qt::LeftButton){ startPos = event->pos(); } } //释放鼠标时,item才会被选中 void TestListWidget::mouseReleaseEvent(QMouseEvent *event) { //如果鼠标释放位置和单击位置相距超过5像素,则不会触发item选中 if((event->pos() - startPos).manhattanLength() > 5) return; TestListWidgetItem *item = static_cast(itemAt(event->pos())); setCurrentItem(item); } //处理鼠标离开后,hover图标回复正常状态 void TestListWidget::leaveEvent(QEvent *event) { Q_UNUSED(event); oldHighlightItem = theHighlightItem; if(oldHighlightItem && !oldHighlightItem->isSelected()) oldHighlightItem->setIcon(oldHighlightItem->Img); oldHighlightItem = theHighlightItem = nullptr; } //响应itemSelectionChanged()信号,处理item被选中后,图标变成并保持hover状态 void TestListWidget::updateSelectedIcon() { oldSelectedItem = theSelectedItem; theSelectedItem = static_cast(currentItem()); //之前被选中的item图标回复原样 //新被选中的item图标变成hover状态 if(oldSelectedItem != theSelectedItem){ if(oldSelectedItem) oldSelectedItem->setIcon(oldSelectedItem->Img); if(theSelectedItem) theSelectedItem->setIcon(theSelectedItem->Img_hover); } }

(3)使用TestListWidget和TestListWidgetItem

void test::initUi() { TestListWidget *listwidget = new TestListWidget(this); listwidget->setIconSize(QSize(25, 25)); //设置item图标大小 listwidget->setFocusPolicy(Qt::NoFocus); //这样可禁用tab键和上下方向键并且除去复选框 listwidget->setFixedHeight(320); listwidget->setFont(QFont("宋体", 10, QFont::DemiBold)); listwidget->setStyleSheet( //"*{outline:0px;}" //除去复选框 "QListWidget{background:rgb(245, 245, 247); border:0px; margin:0px 0px 0px 0px;}" "QListWidget::Item{height:40px; border:0px; padding-left:14px; color:rgba(200, 40, 40, 255);}" "QListWidget::Item:hover{color:rgba(40, 40, 200, 255);}" "QListWidget::Item:selected{background:rgb(230, 231, 234); color:rgba(40, 40, 200, 255); border-left:4px solid rgb(180, 0, 0);}" //"QListWidget::Item:selected:active{background:rgb(230, 231, 234); color:rgba(40, 40, 200, 255); border-left:4px solid rgb(180, 0, 0);}"); TestListWidgetItem *item1 = new TestListWidgetItem(listwidget); item1->setUpIcon(QIcon(":/listBar_Icon/1.png"), QIcon(":/listBar_Icon/1_hover.png")); item1->setText("发现音乐"); TestListWidgetItem *item2 = new TestListWidgetItem(listwidget); item2->setUpIcon(QIcon(":/listBar_Icon/2.png"), QIcon(":/listBar_Icon/2_hover.png")); item2->setText("私人FM"); TestListWidgetItem *item3 = new TestListWidgetItem(listwidget); item3->setUpIcon(QIcon(":/listBar_Icon/3.png"), QIcon(":/listBar_Icon/3_hover.png")); item3->setText("朋友"); TestListWidgetItem *item4 = new TestListWidgetItem(listwidget); item4->setUpIcon(QIcon(":/listBar_Icon/4.png"), QIcon(":/listBar_Icon/4_hover.png")); item4->setText("MV"); TestListWidgetItem *item5 = new TestListWidgetItem(listwidget); item5->setUpIcon(QIcon(":/listBar_Icon/5.png"), QIcon(":/listBar_Icon/5_hover.png")); item5->setText("本地音乐"); TestListWidgetItem *item6 = new TestListWidgetItem(listwidget); item6->setUpIcon(QIcon(":/listBar_Icon/6.png"), QIcon(":/listBar_Icon/6_hover.png")); item6->setText("下载管理"); TestListWidgetItem *item7 = new TestListWidgetItem(listwidget); item7->setUpIcon(QIcon(":/listBar_Icon/7.png"), QIcon(":/listBar_Icon/7_hover.png")); item7->setText("我的音乐云盘"); TestListWidgetItem *item8 = new TestListWidgetItem(listwidget); item8->setUpIcon(QIcon(":/listBar_Icon/8.png"), QIcon(":/listBar_Icon/8_hover.png")); item8->setText("我的收藏"); QVBoxLayout *layout = new QVBoxLayout(this); layout->setSpacing(0); layout->addWidget(listwidget); layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); }

(4)继承QListWidget时其实也可以不需要重写leaveEvent(QEvent *event)和mouseMoveEvent(QMouseEvent *event)这两个函数,只需要重写event(QEvent *event)。

TestListWidget.h文件: class TestListWidget : public QListWidget { Q_OBJECT public: explicit TestListWidget(QWidget *parent = nullptr); protected: void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; bool event(QEvent *event) override; private: QPoint startPos; TestListWidgetItem *theHighlightItem = nullptr; TestListWidgetItem *oldHighlightItem = nullptr; TestListWidgetItem *theSelectedItem = nullptr; TestListWidgetItem *oldSelectedItem = nullptr; private slots: void updateSelectedIcon(); }; TestListWidget.c文件: TestListWidget::TestListWidget(QWidget *parent) : QListWidget(parent) { //不重写mouseMoveEvent(QMouseEvent *event)的话,该属性可以不用设置 //setMouseTracking(true); //当前被选中项发生变化时,触发item图标的更新 connect(this, &TestListWidget::itemSelectionChanged, this, &TestListWidget::updateSelectedIcon); } //鼠标按下时,startPos记录单击位置 void TestListWidget::mousePressEvent(QMouseEvent *event) { if(event->buttons() & Qt::LeftButton){ startPos = event->pos(); } } //释放鼠标时,item才会被选中 void TestListWidget::mouseReleaseEvent(QMouseEvent *event) { //如果鼠标释放位置和单击位置相距超过5像素,则不会触发item选中 if((event->pos() - startPos).manhattanLength() > 5) return; //由于TestListWidgetItem没有QObject属性,所以这里使用static_cast而非qobject_cast TestListWidgetItem *item = static_cast(itemAt(event->pos())); setCurrentItem(item); } bool TestListWidget::event(QEvent *event) { switch (event->type()) { //处理鼠标hover时,item的图标需要变成hover状态 case QEvent::HoverMove: oldHighlightItem = theHighlightItem; //由于TestListWidgetItem没有QObject属性,所以这里使用static_cast而非qobject_cast theHighlightItem = static_cast(itemAt(mapFromGlobal(QCursor::pos()))); //旧的hover的item图标回复原状(条件是该item没有被选中) //新的hover的iten图标变成hover状态(条件是该item没有被选中) if(oldHighlightItem != theHighlightItem){ if(oldHighlightItem && !oldHighlightItem->isSelected()) oldHighlightItem->setIcon(oldHighlightItem->Img); if(theHighlightItem && !theHighlightItem->isSelected()) theHighlightItem->setIcon(theHighlightItem->Img_hover); } break; //处理鼠标离开后,hover图标回复正常状态 case QEvent::HoverLeave: oldHighlightItem = theHighlightItem; if(oldHighlightItem && !oldHighlightItem->isSelected()) oldHighlightItem->setIcon(oldHighlightItem->Img); oldHighlightItem = theHighlightItem = nullptr; break; default: break; } return QListWidget::event(event); } //响应itemSelectionChanged()信号,处理item被选中后,图标变成并保持hover状态 void TestListWidget::updateSelectedIcon() { oldSelectedItem = theSelectedItem; //由于TestListWidgetItem没有QObject属性,所以这里使用static_cast而非qobject_cast theSelectedItem = static_cast(currentItem()); //之前被选中的item图标回复原样 //新被选中的item图标变成hover状态 if(oldSelectedItem != theSelectedItem){ if(oldSelectedItem) oldSelectedItem->setIcon(oldSelectedItem->Img); if(theSelectedItem) theSelectedItem->setIcon(theSelectedItem->Img_hover); } }

这一部分是自己稍加改进的代码,运行无误。还是用的重写事件的方法。

#include "testlistwidgetitem.h" #include #include "testlistwidgetitem.h" #include "testlistwidget.h" #include #include #include #include #include int main(int argc, char *argv[]) { QApplication a(argc, argv); TestListWidget *listwidget = new TestListWidget(); listwidget->setIconSize(QSize(25, 25)); //设置item图标大小 listwidget->setFocusPolicy(Qt::NoFocus); //这样可禁用tab键和上下方向键并且除去复选框 listwidget->setFixedHeight(320); listwidget->setFont(QFont("宋体", 10, QFont::DemiBold)); listwidget->setStyleSheet( "*{outline:0px;}" //除去复选框 "QListWidget{background:rgb(245, 245, 247); border:0px; margin:0px 0px 0px 0px;}" "QListWidget::Item{height:40px; border:0px; padding-left:14px; color:rgba(200, 40, 40, 255);}" "QListWidget::Item:hover{color:rgba(40, 40, 200, 255);}" "QListWidget::Item:selected{background:rgb(230, 231, 234); color:rgba(40, 40, 200, 255); border-left:4px solid rgb(180, 0, 0);}" "QListWidget::Item:selected:active{background:rgb(230, 231, 234); color:rgba(40, 40, 200, 255); border-left:4px solid rgb(180, 0, 0);}"); TestListWidgetItem *item1 = new TestListWidgetItem(listwidget); item1->setUpIcon(QIcon(":/normal.jpg"), QIcon(":/pressed.jpg")); item1->setText("数据查询"); TestListWidgetItem *item2 = new TestListWidgetItem(listwidget); item2->setUpIcon(QIcon(":/normal1.jpg"), QIcon(":/pressed1.jpg")); item2->setText("曲线查询"); QVBoxLayout *layout = new QVBoxLayout(); //QHBoxLayout *layout = new QHBoxLayout(); layout->setSpacing(0); layout->addWidget(listwidget); layout->setContentsMargins(0, 0, 0, 0); //listwidget->setLayout(layout); //不注掉这一句的话不显示窗体,很奇怪 listwidget->show(); return a.exec(); }

 

 



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


    图片新闻

    实验室药品柜的特性有哪些
    实验室药品柜是实验室家具的重要组成部分之一,主要
    小学科学实验中有哪些教学
    计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
    实验室各种仪器原理动图讲
    1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
    高中化学常见仪器及实验装
    1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
    微生物操作主要设备和器具
    今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
    浅谈通风柜使用基本常识
     众所周知,通风柜功能中最主要的就是排气功能。在

    专题文章

      CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭